﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using AliyunDDNS.Core;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.Caching.Memory;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.Logging;
using Microsoft.Net.Http.Headers;

namespace AliyunDDNS.Web.Controllers
{
    [Produces("application/json")]
    [Route("Ddns/{token}")]
    public class DdnsController : Controller
    {
        private readonly ILogger<DdnsController> logger;
        private readonly IAliyunDdnsService aliyunDdnsService;
        private readonly IMemoryCache cache;
        private readonly string ipCacheKey = "CurrentHomeIP";
        private readonly string tokenKey;

        public DdnsController(ILogger<DdnsController> logger, IConfiguration configuration,
            IAliyunDdnsService aliyunDdnsService,
            IMemoryCache cache)
        {
            this.logger = logger;
            this.aliyunDdnsService = aliyunDdnsService;
            this.cache = cache;
            tokenKey = configuration.GetSection("tokenKey").Value;
        }
 
        public async Task<JsonResult> Index(string token)
        {
            var key = DdnsHelper.ComposeToken(token,tokenKey);
 
            var userAgent = Request.Headers.SingleOrDefault(c => c.Key == HeaderNames.UserAgent).Value.ToString().Replace("{", "").Replace("}", "");

            logger.LogInformation($"userAgent：{userAgent}");

            if (!DdnsHelper.VerifyToken(key, userAgent))
            {
                logger.LogWarning("token无效");
                return Json("error");
            }

            await PreUpdateDomainRecordCheck();

            return Json("ok");
        }

        private async Task PreUpdateDomainRecordCheck()
        {
            var userIP = Request.Headers["X-Forwarded-For"].FirstOrDefault();
            if (string.IsNullOrEmpty(userIP))
            {
                userIP = Request.HttpContext.Connection.RemoteIpAddress.ToString();
            }
            logger.LogInformation($"Client IP：{userIP}");

            var nowIp = cache.Get(ipCacheKey);
            if (nowIp != null && nowIp.ToString() == userIP)
            {
                logger.LogInformation($"No update required.");
                return;
            }

            cache.Set(ipCacheKey, userIP, new TimeSpan(5, 0, 0, 0));
            await UpdateDomainRecord(userIP);
        }

        private async Task UpdateDomainRecord(string userIP)
        {
            await Task.Run(() => aliyunDdnsService.UpdateDomainRecord(userIP));
        }
    }
}